今天來整理一下使用 HTTP GET,POST,DO 的資料請求通訊方式讀取資料的操作。
一般要從網路上讀取資料,在p5.js中,提供了3種常見的方法
httpGet() 用於以URL的連結讀取資料,不用上傳相關參數資料。
httpPost() 用於以URL的連結讀取資料,不用上傳相關參數資料。
httpDo() 比較是通用型的讀取資料協定格式
httpGet(path, [datatype], [data], [callback], [errorCallback])
httpGet(path, data, [callback], [errorCallback])
httpGet(path, callback, [errorCallback])
httpPost(path, [datatype], [data], [callback], [errorCallback])
httpPost(path, data, [callback], [errorCallback])
httpPost(path, callback, [errorCallback])
httpDo(path, [method], [datatype], [data], [callback], [errorCallback])
httpDo(path, options, [callback], [errorCallback])
path: URL
datatype: "json", "jsonp", "binary", "arrayBuffer", "xml", or "text"
data: Object|Boolean -> {id:"123", name:"jason"}, false/true
不過經過測試發現p5.js提供的 httpGet(),httpPost(),httpDo()這3種方法,只有支援GET的method,
POST的方法無法將參數傳送出去,因此只能使用 在URL中串參數的方法,
結果就是只能使用 httpGet(path, [datatype], [callback])
其中URL加上參數的格式 例如: getData.php?id=123&name=jason
let url = "https://tcgbusfs.blob.core.windows.net/blobtcmsv/TCMSV_alldesc.json";
function setup() {
const xget = httpGet(url, 'json', false, (res) => {
console.log(res); //-- 回傳結果在 PromiseResult 中
console.log(xget); //-- 建立 Promise 物件
});
}
JSON資料來源為 政府資料開放平台「臺北市停車場資訊V2」,網址為 https://data.gov.tw/dataset/128435
讀取到的資料如下
有時候在讀取資料時會發生CORS的問題,
這時就要透過PHP來當作中介讀取資料,再回傳給前端
JS
let url = "getData_GET.php?urlx=https://sme.moeasmea.gov.tw/startup/upload/opendata/gov_source_map_opendata.json";
const xget = httpGet(url, 'json', false, (res) => {
console.log(res);
console.log(xget);
});
PHP (getData_GET.php)
<?php
$urlx = $_GET["urlx"];
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded',
//'content' => $postdata
)
);
$context = stream_context_create($opts);
$result = file_get_contents($urlx, false, $context);
echo $result;
?>
接著來看一下Native JS的方法,使用的是 XMLHttpRequest()
let url = "https://tcgbusfs.blob.core.windows.net/blobtcmsv/TCMSV_alldesc.json";
const xhttp = new XMLHttpRequest(); //-- 建立 XMLHttpRequest物件
xhttp.onload = function() {
console.log(this);
console.log(this.responseText);
console.log(this.getResponseHeader("Last-Modified")); //-- 讀取head表頭參數 Last-Modified 的內容
console.log(this.getAllResponseHeaders()); //-- 讀取全部head表頭參數的內容
}
xhttp.open("GET", url, true);
xhttp.send();
查看一下XMLHttpRequest物件的屬性及方法
JS
let url = "getData_GET.php?id=2&name=Jason";
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
console.log(this.responseText);
console.log(this.getAllResponseHeaders());
}
xhttp.open("GET", url, true);
xhttp.send();
PHP (getData_GET.php)
<?php
echo $_GET["id"].", ".$_GET["name"];
?>
JS
let url = "getData_POST.php";
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
console.log(this.responseText);
console.log(this.getAllResponseHeaders());
}
xhttp.open("POST", url);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("id=2&name=Jason");
PHP (getData_POST.php)
<?php
echo $_POST["id"].", ".$_POST["name"];
?>
如果回傳內容是JSON格式,要另外用JSON物件轉換
let url = "https://tcgbusfs.blob.core.windows.net/blobtcmsv/TCMSV_alldesc.json";
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
console.log(this);
const json_obj = JSON.parse(this.responseText);
console.log(json_obj);
console.log(this.getAllResponseHeaders());
}
xhttp.open("GET", url, true);
xhttp.send();
有時候在讀取資料時會發生CORS的問題,
這時就要透過PHP來當作中介讀取資料,再回傳給前端
JS
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
const json_obj = JSON.parse(this.responseText);
console.log(json_obj);
console.log(this.getAllResponseHeaders());
}
xhttp.open("POST", "getData_POST.php");
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("urlx=https://sme.moeasmea.gov.tw/startup/upload/opendata/gov_source_map_opendata.json");
PHP (getData_POST.php)
<?php
$urlx = $_POST["urlx"];
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-Type: application/x-www-form-urlencoded',
)
);
$context = stream_context_create($opts);
$result = file_get_contents($urlx, false, $context);
echo $result;
?>
php用到的指令
stream_context_create(?array $options = null, ?array $params = null): resource
file_get_contents(
string $filename,
bool $use_include_path = false,
?resource $context = null,
int $offset = 0,
?int $length = null
): string|false
另外,在以POST傳送資料時,可以先用物件格式編輯參數內容,轉換成 url query parameters的格式
let postData = {
id: 123,
name: "Jason"
};
let pdata = Object.entries(postData).map( ([key, val]) => `${key}=${val}` ).join('&');
console.log(pdata); //-- id=123&name=Jason
其中 Object.entries(postData) 是將object轉換成陣列
console.log(Object.entries(postData));
再利用 map(([key, val]) => ${key}=${val}
) 組合 參數對陣列
console.log(Object.entries(postData).map(([key, val]) => `${key}=${val}`));
最後再用 join('&') 將參數對陣列串接成字串,並以'&'串接
console.log(Object.entries(postData).map(([key, val]) => `${key}=${val}`).join('&'));
最後的程式碼
let postData = {
urlx: "https://sme.moeasmea.gov.tw/startup/upload/opendata/gov_source_map_opendata.json",
};
function setup() {
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
const json_obj = JSON.parse(this.responseText);
console.log(json_obj);
console.log(this.getAllResponseHeaders());
}
let pdata = Object.entries(postData).map(([key, val]) => `${key}=${val}`).join('&');
xhttp.open("POST", "getData_POST.php");
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(pdata);
}
參考資料
httpGet()
https://p5js.org/reference/#/p5/httpGet
JavaScript Array join()
https://www.w3schools.com/jsref/jsref_join.asp
AJAX - The XMLHttpRequest Object
https://www.w3schools.com/js/js_ajax_http.asp
file_get_contents
https://www.php.net/manual/zh/function.file-get-contents.php
stream_context_create
https://www.php.net/manual/zh/function.stream-context-create.php